package com.sz.web.autoconfig;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sz.framework.threadlocal.SzDefaultThreadLocal;
import com.sz.framework.threadlocal.SzThreadLocal;
import com.sz.framework.trace.SzTraceIdDetector;
import com.sz.framework.trace.SzTraceIdDetectorAggregator;
import com.sz.framework.trace.SzUUIDTraceIdDetector;
import com.sz.web.advice.GlobalExceptionHandler;
import com.sz.web.advice.ResponseResultAdvice;
import com.sz.web.context.request.CachingRequestBodyFilter;
import com.sz.web.jackson.SzJacksonModule;
import com.sz.web.properties.WebProperties;
import jakarta.annotation.Resource;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * @author: yxl
 * 2025-07-23
 */

@AutoConfiguration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@EnableConfigurationProperties(WebProperties.class)
public class SzWebAutoConfiguration implements WebMvcConfigurer {

    @Resource
    private WebProperties webProperties;

    /**
     * 请求路径前缀
     * @param configurer /
     */
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix(webProperties.getApiPrefix(), c -> true);
    }


    /**
     * JSON序列化
     *
     * @return
     */
    @Bean
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        return new Jackson2ObjectMapperBuilder().failOnUnknownProperties(false).featuresToDisable(com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS).modulesToInstall(new SzJacksonModule());
    }

    @Bean
    public SzTraceIdDetector szTraceIdDetector() {
        SzThreadLocal threadLocal = new SzDefaultThreadLocal(new ThreadLocal());
        return new SzUUIDTraceIdDetector(threadLocal);
    }

    @Bean
    public SzTraceIdDetectorAggregator szTraceIdDetectorAggregator(List<SzTraceIdDetector> detectors) {
        return new SzTraceIdDetectorAggregator(detectors);
    }

    /**
     * requestBody可复制
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean<CachingRequestBodyFilter> cachingRequestBodyFilter(SzTraceIdDetectorAggregator traceIdDetectorAggregator) {
        FilterRegistrationBean<CachingRequestBodyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new CachingRequestBodyFilter(traceIdDetectorAggregator));
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        return registrationBean;
    }

    @Bean
    public GlobalExceptionHandler globalExceptionHandler(ObjectMapper objectMapper) {
        return new GlobalExceptionHandler(objectMapper);
    }

    @Bean
    public ResponseResultAdvice responseResultAdvice(ObjectMapper objectMapper) {
        return new ResponseResultAdvice(objectMapper);
    }




}
